home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / AOCE Sample Code / PowerTalk Access Modules / Sample SMSAM / SampleSMSAM Source / 2020HalfGateway / 2020HalfGateway.cp next >
Encoding:
Text File  |  1995-07-28  |  33.8 KB  |  1,282 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        2020HalfGateway.cp
  3.  
  4.     Copyright:    © 1991-1994 by Apple Computer, Inc.
  5.                 All rights reserved.
  6.  
  7.     Part of the AOCE Sample SMSAM Package.  Consult the license
  8.     which came with this software for your specific legal rights.
  9.  
  10. */
  11.  
  12.  
  13.  
  14. #ifndef __BLJSTANDARDINCLUDES__
  15. #include "BLJStandardIncludes.h"
  16. #endif
  17.  
  18. #ifndef __2020HALFGATEWAY__
  19. #include "2020HalfGateway.h"
  20. #endif
  21.  
  22. #ifndef __OCE__
  23. #include <OCE.h>
  24. #endif
  25.  
  26. #ifndef __OCEMAIL__
  27. #include <OCEMail.h>
  28. #endif
  29.  
  30. #ifndef __OCEMESSAGING__
  31. #include "OCEMessaging.h"
  32. #endif
  33.  
  34. #ifndef __OCESTANDARDDIRECTORY__
  35. #include  <OCEStandardDirectory.h>
  36. #endif
  37.  
  38. #ifndef __MAILBUFFER__
  39. #include "MailBuffer.h"
  40. #endif
  41.  
  42. #ifndef __DEBUGGINGGEAR__
  43. #include "DebuggingGear.h"
  44. #endif
  45.  
  46. #ifndef __LETTERLOGWINDOW__
  47. #include "LetterLogWindow.h"
  48. #endif
  49.  
  50. #ifndef __MAILGATEWAY__
  51. #include "MailGateway.h"
  52. #endif
  53.  
  54. #ifndef __UTILITIES__
  55. #include "Utilities.h"
  56. #endif
  57.  
  58. #ifndef __RECIPIENT__
  59. #include "Recipient.h"
  60. #endif
  61.  
  62. #ifndef __STRING__
  63. #include "String.h"
  64. #endif
  65.  
  66. #ifndef __STATUSDATABASE__
  67. #include "StatusDatabase.h"
  68. #endif
  69.  
  70. #ifndef __AYSTHREADGLUE__
  71. #include "AYSThreadGlue.h"
  72. #endif
  73.  
  74. #ifndef __LETTERLOG__
  75. #include "LetterLog.h"
  76. #endif
  77.  
  78. #ifndef __BLJOCEUTILITIES__
  79. #include "BLJOCEUtilities.h"
  80. #endif
  81.  
  82. #ifndef __THREADUTILITIES__
  83. // #include "ThreadUtilities.h"
  84. #endif
  85.  
  86. #ifndef    __RESOURCES__
  87. #include "Resources.h"
  88. #endif
  89.  
  90. #ifndef __DATAITEM__
  91. #include "DataItem.h"
  92. #endif
  93.  
  94. /***********************************|****************************************/
  95.  
  96. #pragma segment T2020HalfGateway
  97.  
  98. /***********************************|****************************************/
  99.  
  100. ImplementQueue(T2020Letter,T2020LetterQueue,true);
  101.  
  102. /***********************************|****************************************/
  103.  
  104. const short pictID = 1001;
  105.  
  106. /***********************************|****************************************/
  107.  
  108. T2020HalfGateway* g2020HalfGateway = nil;
  109.  
  110. TLetterLogWindow* gAOCELetterLogWindow = nil;
  111.  
  112. #if debug
  113. Boolean gReenumerating = false;
  114. #endif
  115.  
  116. /***********************************|****************************************/
  117.  
  118. T2020HalfGateway::T2020HalfGateway ():
  119.     THalfGateway (),
  120.     fWorkingVRefNum ( 0 ),
  121.     fWorkingDirID ( 0 ),
  122.     fShuttingDown ( false ),
  123.     fInRecoveryPhase ( false ),
  124.     fRecoveryPhaseScanThread ( nil ),
  125.     fPeriodicTasksThread ( nil ),
  126.     fRunThreadH ( nil ),
  127.     fScan2020ThreadH ( nil ),
  128.     fPutLettersInto2020ThreadH ( nil ),
  129.     fSendLettersFromOCEToMailGatewayThreadH ( nil ),
  130.     fProcessLetterRecipientReportsThreadH ( nil ),
  131.     fAvailable2020Directories (),
  132.     fReceivedLetters (),
  133.     fLettersFromOCEToBeSent (),
  134.     fReportsFromOCEToBeProcessed (),
  135.     fLettersWaitingForRecipientReports (),
  136.     fDoNotSendLetters ( false ),
  137.     fDoNotReceiveLetters ( false ),
  138.     fNextTimeToUpdateListOfKnownExtendedDirectories ( 0 ),
  139.     fLettersWaitingForRecipientReportsCountdownTimer ( kOneHourInSeconds * 5 )
  140. {
  141. #if debug
  142.     g2020HalfGateway = this;
  143. #endif
  144.  
  145.     ResetStatistics ( );
  146.     
  147.     fAOCEServerHint.aNet = fAOCEServerHint.aNode = fAOCEServerHint.aSocket = 0;
  148. }
  149.  
  150. /***********************************|****************************************/
  151.  
  152. T2020HalfGateway::~T2020HalfGateway ()
  153. {
  154. }
  155.  
  156. /***********************************|****************************************/
  157.  
  158. void T2020HalfGateway::PutReceivedLettersInto2020()
  159. {
  160.     do
  161.     {
  162.         TLetter    *receivedLetter = fReceivedLetters.Remove();
  163.  
  164.         while ( receivedLetter )
  165.         {
  166.             ReceiveALetter (receivedLetter);
  167.             receivedLetter = fReceivedLetters.Remove();
  168.         }
  169.  
  170. #if debug
  171.         TSleep( 15 * 60 );
  172. #else
  173.         TSleep(60*10);
  174. #endif
  175.  
  176.     }
  177.     while (IsHalfGatewayShuttingDown() == false);
  178. }
  179.  
  180. /***********************************|****************************************/
  181.  
  182. Boolean    T2020HalfGateway::ReceiveLetter (TLetter* letter)
  183. {
  184.     //    Update the status item for the number of letters received into 2020
  185. #if STATUSVARIABLELETTERSFROMMGTOAYSISDEFINED
  186.     IncrementLongStatus(kTotalLettersFromMGtoAYS);
  187. #endif
  188.  
  189.     //    And put this letter into the queue of letters waiting to be processed.
  190.     fReceivedLetters.Append(letter);
  191.  
  192.     return true;
  193. }
  194.  
  195. /***********************************|****************************************/
  196.  
  197. void T2020HalfGateway::SendOCELettersToMailGateway() 
  198. {
  199.     do 
  200.     {
  201.         T2020Letter *letter = fLettersFromOCEToBeSent.Remove();
  202.  
  203.         if (letter) 
  204.         {
  205.             SendLetter(letter);
  206.             TYield();
  207.         } 
  208.         else 
  209.         {
  210.             TSleep(60*15);
  211.         }
  212.     } 
  213.     while (IsHalfGatewayShuttingDown() == false);
  214. }
  215.  
  216. /***********************************|****************************************/
  217.  
  218. void T2020HalfGateway::ProcessLetterRecipientReports()
  219. {
  220.     do
  221.     {
  222.         T2020Letter *report = fReportsFromOCEToBeProcessed.Remove();
  223.  
  224.         if (report)
  225.         {
  226.             HandleRecipientReport(report);
  227.             TYield();
  228.         }
  229.         else
  230.         {
  231.             TSleep(60*15);
  232.         }
  233.     }
  234.     while (IsHalfGatewayShuttingDown() == false);
  235. }
  236.  
  237. /***********************************|****************************************/
  238.  
  239. void T2020HalfGateway::Scan2020ForOutgoingLetters ()
  240. {
  241.     do {
  242.         MSAMEnumeratePB pb;
  243.  
  244.         if ( GetServerQueueID () ) 
  245.         {
  246.  
  247.             TRY
  248.             {
  249.                 memset(&pb, 0, sizeof(pb));
  250.                 pb.queueRef = GetServerQueueID();
  251.                 pb.startSeqNum = fEnumerateStartSeqNum;
  252.                 pb.buffer = AllocateMailBuffer(512);
  253.  
  254.                 FAILOSErr(MSAMEnumerateSleep ((MSAMParam*) &pb));
  255.  
  256.                 //    Now, step through this list, and handle each item.
  257.                 short numberOfItems = * (short *) pb.buffer.buffer;
  258.                 MSAMEnumerateOutQReply *itemP = (MSAMEnumerateOutQReply *) ((char *) pb.buffer.buffer + sizeof(short));
  259.  
  260.                 keithF ( 2, "GWEnumerate: items: " << numberOfItems );
  261.  
  262.                 for ( ; numberOfItems > 0; --numberOfItems, ++itemP) 
  263.                 {
  264.                     keithF ( 2, "Item #" << itemP->seqNum << " Resolved? " << (short) itemP->done << " size " << itemP->approxSize );
  265.  
  266.                     if (pb.nextSeqNum > 0)
  267.                         fEnumerateStartSeqNum = pb.nextSeqNum;
  268.                     else
  269.                         fEnumerateStartSeqNum = itemP->seqNum+1;
  270. #if debug
  271.                     //    If debug flag 5 is on, then delete letters instead of  erasing them.
  272.                     if (keithFlag.Flag(25)) 
  273.                     {
  274.                         MSAMDeletePB pb;
  275.  
  276.                         keith << "2020HGwy: DELETING item seq#" << itemP->seqNum << " instead of handling it." << endl;
  277.  
  278.                         pb.queueRef = GetServerQueueID();
  279.                         pb.seqNum = itemP->seqNum;
  280.                         // pb.result = kIPMNoInformation;  // shouldn't be necessary, but do it anyway
  281.  
  282.                         OSErr err = MSAMDeleteSleep((MSAMParam*) &pb);
  283.  
  284.                         if (err)
  285.                             keith << "GWDelete: err#=" << err << endl;
  286.  
  287.                         itemP->done = true;
  288.                         continue;
  289.                     }
  290.  
  291.                     if (gReenumerating) 
  292.                     {
  293.                         itemP->done = false;
  294.                     }
  295. #endif
  296.                     if (itemP->done == false)
  297.                     {
  298.                         T2020Letter *letter = new T2020Letter(this, GetServerQueueID(), itemP->seqNum);
  299.                         Boolean        yesItIs;
  300.  
  301.                         FAILifFALSE(letter->IsLetterAReport(yesItIs));
  302.                         if (yesItIs) 
  303.                         {
  304.                             fReportsFromOCEToBeProcessed.Append(letter);
  305.                         } 
  306.                         else if (fDoNotSendLetters) 
  307.                         {
  308.                             keithDB("T2020HGwy::Scan2020…, letter not sent becaues fDoNotSendLetters == true.");
  309.                             
  310.                             //    Go thru and mark all of the recipients as 'not' received.
  311.                             for (RecipientTypeSet recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
  312.                                 for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount(recipientType); ++recipientIndex) {
  313.                                     TRecipient* recipient = letter->GetRecipient(recipientType, recipientIndex);
  314.                                     recipient->SetStatus(cNotReceived);
  315.                                 }
  316.                             }
  317.                             
  318.                             //    And we're done with the letter.
  319.                             if ( ! letter->LetterIsCompleted() )
  320.                                 delete letter;
  321.                         }
  322.                         else
  323.                         {
  324.                             fLettersFromOCEToBeSent.Append(letter);
  325.                         }
  326.                     }
  327.  
  328.                     TYield();
  329.                 }
  330. #if debug
  331.                 gReenumerating = false;
  332. #endif
  333.             }
  334.             EXCEPTION
  335.             {
  336. #if debug
  337.                 keith << "GWEnumerate, FAILURE.  err=" << EXCEPTIONCODE << endl;
  338. #endif
  339.             }
  340.             ENDEXCEPTION;
  341.  
  342.             DisposeMailBuffer(pb.buffer);
  343.         }
  344.  
  345.         //    Now, sleep for a while...
  346.         TSleep(60*15);
  347.  
  348.     } while (IsHalfGatewayShuttingDown() == false);
  349. }
  350.  
  351. /***********************************|****************************************/
  352.  
  353.  
  354. void DoResendLettersAtStartupWrapper (unsigned long g, unsigned long ) 
  355. {
  356.     TSetRefCon('2Scn');
  357.     ( (T2020HalfGateway*) g )->ResendLettersAtStartup ();
  358. }
  359.  
  360. /***********************************|****************************************/
  361.  
  362. void T2020HalfGateway::ResendLettersAtStartup() 
  363. {
  364.     Boolean done = false;
  365.  
  366.     #if debug
  367.     if (keithFlag.Flag ( 25 ) )    {
  368.         keithDB ( "T2020HalfGateway::ResendLettersAtStartup(), skipping recovery since keithFlag(25) is set." );
  369.         done = true;
  370.     }    
  371.     #endif
  372.     
  373.     while ((IsHalfGatewayShuttingDown() == false) && (done == false))
  374.     {    
  375.         if (GetServerQueueID()) 
  376.         {
  377.             MSAMEnumeratePB pb;
  378.  
  379.             TRY
  380.                 memset(&pb, 0, sizeof(pb));
  381.                 pb.queueRef = GetServerQueueID();
  382.                 pb.startSeqNum = fEnumerateStartSeqNum;
  383.                 pb.buffer = AllocateMailBuffer(512);
  384.  
  385.                 FAILOSErr(MSAMEnumerateSleep ((MSAMParam*) &pb));
  386.  
  387.                 //    Now, step through this list, and handle each item.
  388.                 short numberOfItems = * (short *) pb.buffer.buffer;
  389.                 MSAMEnumerateOutQReply *itemP = (MSAMEnumerateOutQReply *) ((char *) pb.buffer.buffer + sizeof(short));
  390.  
  391.                 keithF ( 2, "GWEnumerate: items: " << numberOfItems );
  392.  
  393.                 for ( ; numberOfItems > 0; --numberOfItems, ++itemP) 
  394.                 {
  395.                     keithF ( 2, keith << "Item #" << itemP->seqNum << " Resolved? " << (short) itemP->done << " size " << itemP->approxSize );
  396.                     
  397.                     if (itemP->done == false) 
  398.                     {
  399.                         T2020Letter *letter = new T2020Letter(this, GetServerQueueID(), itemP->seqNum);
  400.                         Boolean        yesItIs;
  401.  
  402.                         if ((letter->IsLetterAReport(yesItIs)) && (yesItIs == true))
  403.                         {
  404.                             //    Since this is a report, put it into the list of reports to be processed.
  405.                             //    There will get handled once the server gateway has finished this
  406.                             //    recovery phase and actually starts running.
  407.                             fReportsFromOCEToBeProcessed.Append(letter);
  408.                         }
  409.                         else
  410.                         {
  411. #if debug
  412.                             if (keithFlag.Flag(2))
  413.                             {
  414.                                 TRString    subject;
  415.                                 letter->GetSubject(subject);
  416.                                 keith << "T2020Hgwy: Resending letter " << subject << " in startup phase." << endl;
  417.                             }
  418. #endif
  419.                             ResendLetter(letter);
  420.                         }
  421.                     } else {
  422.                         //    All of the recipients for this letter have been 'completed'; so delete the letter.
  423.                         MSAMDeletePB deletePB;
  424.                 
  425.                         deletePB.queueRef = GetServerQueueID();
  426.                         deletePB.seqNum = itemP->seqNum;
  427.                         deletePB.result = noErr;
  428.                 
  429.                         keithF ( 1, "2020HalfGwy::Deleting letter " << itemP->seqNum << " from OCE queue." );
  430.                         
  431.                         OSErr err = MSAMDeleteSleep((MSAMParam*) &deletePB);
  432.                     }
  433.  
  434.                     fEnumerateStartSeqNum = max(fEnumerateStartSeqNum, itemP->seqNum+1);
  435.                 }
  436.  
  437.                 //    When we've run out of items to enumerate, then we're done, so exit this loop.
  438.                 if (pb.nextSeqNum <= 0)
  439.                     done = true;
  440.                 else 
  441.                     fEnumerateStartSeqNum = pb.nextSeqNum;
  442.  
  443.             NOHANDLER;
  444.             
  445.             DisposeMailBuffer ( pb.buffer );
  446.         }
  447.  
  448.         //    Now, sleep for a while...
  449.         TSleep(60);
  450.     };
  451.  
  452.     fInRecoveryPhase = false;
  453.     fRecoveryPhaseScanThread = nil;
  454. }
  455.  
  456. /***********************************|****************************************/
  457.  
  458. #if debug
  459. void ReenumerateLast2020Letter() 
  460. {
  461.     if (g2020HalfGateway) {
  462.         g2020HalfGateway->fEnumerateStartSeqNum--;
  463.         gReenumerating = true;
  464.     }
  465. }
  466.  
  467. void ReenumerateAll2020Letters() 
  468. {
  469.     if (g2020HalfGateway) {
  470.         g2020HalfGateway->fEnumerateStartSeqNum = 0;
  471.         gReenumerating = true;
  472.     }
  473. }
  474. #endif
  475.  
  476. /***********************************|****************************************/
  477.  
  478. Boolean T2020HalfGateway::SendLetter (TLetter *letter) 
  479. {
  480.     #define AOCEB6C5SSERVERSENDSMELETTERSISHOULDNOTGET 0
  481.     #if AOCEB6C5SSERVERSENDSMELETTERSISHOULDNOTGET
  482.     TRecipient * recipient = letter->GetRecipient ( fromRecipient, 1 );
  483.     
  484.     if ( recipient && recipient->IsAddressTypePresent() && recipient->GetAddressType() == 'ALNK')
  485.     {
  486.         if ( ! letter->LetterIsCompleted() )
  487.             delete letter;
  488.         return true;
  489.     }
  490.     #endif
  491.     
  492.     fLettersReceivedFromAOCE++;
  493.     return fMailGateway->ReceiveLetter (letter, this);
  494. }
  495.  
  496. /***********************************|****************************************/
  497.  
  498. Boolean T2020HalfGateway::BeginRecoveryPhase()
  499. {
  500. #if debug
  501.     if (keithFlag.Flag(2)) {
  502.         keith << "T2020Hgwy: BEGIN RECOVERY PHASE" << endl;
  503.     }
  504. #endif
  505.  
  506.     fInRecoveryPhase = true;
  507.  
  508.     fRecoveryPhaseScanThread = createThread ('2Rsc', &DoResendLettersAtStartupWrapper, 32000, (unsigned long) this, 0, TNormalMode);
  509.  
  510.     return true;
  511. }
  512.  
  513. /***********************************|****************************************/
  514.  
  515. Boolean T2020HalfGateway::IsRecoveryDone() 
  516. {
  517.     return (fInRecoveryPhase == false);
  518. }
  519.  
  520. /***********************************|****************************************/
  521.  
  522. Boolean T2020HalfGateway::FinishRecoveryPhase() 
  523. {
  524.     //    Make sure we've finished the recovery phase
  525.     while (IsRecoveryDone() == false)
  526.         TYield();
  527.  
  528. #if debug
  529.     if (keithFlag.Flag(2)) {
  530.         keith << "T2020Hgwy: FINISH RECOVERY PHASE" << endl;
  531.     }
  532. #endif
  533.  
  534.     return true;
  535. }
  536.  
  537. /***********************************|****************************************/
  538.  
  539. Boolean T2020HalfGateway::ResendLetter (TLetter* letter)
  540. {
  541.     Boolean result = false;
  542.     
  543.     {    CTupleKey key ("2020DoNotSendLetters");
  544.         CDataItem buffer;
  545.     
  546.         if (GetConfigItem(key, buffer))
  547.             fDoNotSendLetters = * (Boolean *) buffer.GetPhysicalStart();
  548.         else
  549.             fDoNotSendLetters = false;
  550.     }
  551.  
  552.     if (fDoNotSendLetters) {
  553.         keithDB("T2020HGwy::Scan2020…, letter not sent becaues fDoNotSendLetters == true.");
  554.         
  555.         //    Go thru and mark all of the recipients as 'not' received.
  556.         for (RecipientTypeSet recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
  557.             for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount(recipientType); ++recipientIndex) {
  558.                 TRecipient* recipient = letter->GetRecipient(recipientType, recipientIndex);
  559.                 recipient->SetStatus(cNotReceived);
  560.             }
  561.         }
  562.         
  563.         //    And we're done with the letter.
  564.         if (letter->LetterIsCompleted() == false)
  565.             delete letter;
  566.     } else {
  567.         fLettersReceivedFromAOCE++;
  568.         result = fMailGateway->RereceiveLetter (letter, this);
  569.     }
  570.     
  571.     return result;
  572. }
  573.  
  574. /***********************************|****************************************/
  575.  
  576. Boolean T2020HalfGateway::RereceiveLetter (TLetter* letter)
  577. {
  578.  
  579.     #if debug    
  580.     //    TEMPORARY!!        Go through this letter, and mark all of the recipient's status
  581.     //                    codes to cReceived.  Eventually, when the ack architecture is
  582.     //                    done, this code goes away, but currently it lets us behave and
  583.     //                    not infinitely resend mail if we crash frequently.
  584.     if (steveFlag.Flag(9)) {
  585.         // This temporary for Connector
  586.         if (steveFlag.Flag(11)) {
  587.             keith << "2020Hgwy: Setting all recipients’ status == cReceived because steveFlag(9)=true." << endl;
  588.         }
  589.         
  590.         for (unsigned short recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) 
  591.         {
  592.             for (unsigned short index = 1; index <= letter->GetRecipientCount((RecipientTypeSet) recipientType); ++index) 
  593.             {
  594.                 TRecipient* recipient = letter->GetRecipient((RecipientTypeSet) recipientType, index);
  595.                 if (recipient->GetResponsible()) {
  596.                     letter->SetRecipientStatus((RecipientTypeSet) recipientType, index, cReceived);
  597.                 }
  598.             }
  599.         }
  600.  
  601.         if (letter->LetterIsCompleted() == false) {
  602.             delete letter;
  603.         };
  604.         
  605.         return true;
  606.     }
  607.     #endif
  608.  
  609.     //    If the letter has any responsible recipients with a status different from cUnknown,
  610.     //    then that letter must already have been sent to Applelink and a report on those
  611.     //    recipients received.  Thus, we don't have to resend it.  However, if none of the recipients
  612.     //    have been reported on, then we always resend the letter even though it may have already been
  613.     //    sent but we crashed before receiving the first recipient report.
  614.     //
  615.     Boolean letterShouldBeResent = true;
  616.     for (unsigned short recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
  617.         for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount((RecipientTypeSet) recipientType); ++recipientIndex) {
  618.             TRecipient* recipient = letter->GetRecipient((RecipientTypeSet) recipientType, recipientIndex);
  619.             
  620.             if ((recipient) && (recipient->GetResponsible())) {
  621.                 RecipientStatusSet recipientStatus;
  622.                 if (letter->GetRecipientStatus((RecipientTypeSet) recipientType, recipientIndex, recipientStatus) && (recipientStatus != cUnknown)) {
  623.                     letterShouldBeResent = false;
  624.                     break;
  625.                 }
  626.             }
  627.         }
  628.     }
  629.     
  630.     //    Now, either resend the letter or just keep it in the list of letters for acknowledgement purposes.
  631.     if (letterShouldBeResent) {
  632.         //    Put this letter where it will be received just like normal.
  633.         fReceivedLetters.Append(letter);
  634.     } else {
  635.         fLettersWaitingForRecipientReports.Append(letter);
  636.     }
  637.  
  638.     return true;
  639. }
  640.  
  641. /***********************************|****************************************/
  642.  
  643. static Boolean ConvertStatusToAOCERecpientStatusCode ( const RecipientStatusSet status, short& aoceRecipientStatus )
  644. {    Boolean result = true;
  645.  
  646.     switch ( status )
  647.     {
  648.         case cReceived:
  649.             aoceRecipientStatus = noErr; break;
  650.         
  651.         case cNoSuchRecipient:
  652.             aoceRecipientStatus = kIPMNoSuchRecipient; break;
  653.  
  654.         case cTimedOut:
  655.             aoceRecipientStatus = kIPMMsgExpired; break;
  656.  
  657.         case cNotResponsible:    // should never happen
  658.             aoceRecipientStatus = kIPMNoSuchRecipient; break;
  659.  
  660.         case cAmbiguousRecipient:
  661.             aoceRecipientStatus = kIPMRecipientAmbiguous; break;
  662.  
  663.         case cBadRecipient:
  664.         case cUnknown:    //    This should never happen
  665.             aoceRecipientStatus = kIPMRecipientMalformed; break;
  666.  
  667.         case cMessageRejectedByDest:
  668.         case cCanNotSupportBCCRecipient:
  669.         case cNotReceived:
  670.             aoceRecipientStatus = kIPMNoTransferMsgRejectedbyDest; break;
  671.             
  672.         case cRecipientCanNotSendToThisAddress:
  673.             aoceRecipientStatus = kIPMRecipientAccessDenied; break;
  674.             
  675.         case cCanNotTranslateContentForRecipient:
  676.             aoceRecipientStatus = kIPMMsgUnreadable; break;
  677.             
  678.         case cGroupExpansionProblem:
  679.             aoceRecipientStatus = kIPMGroupExpansionProblem; break;
  680.  
  681.         case cNoTranslatableContent:    
  682.         case cRequireTEXTContent:
  683.             aoceRecipientStatus = kIPMRecipientReqStdCont; break;
  684.             
  685.         case cRequireIMAGContent:
  686.             aoceRecipientStatus = kIPMRecipientReqSnapShot; break;
  687.             
  688.         case cLetterTooLarge:
  689.             aoceRecipientStatus = kIPMNoTransferMsgTooLarge; break;
  690.             
  691.         case cGatewayDiskTemporarilyTooFull:
  692.             aoceRecipientStatus = kIPMNoTransferDiskFull; break;
  693.             
  694.         default:
  695.             aoceRecipientStatus = -1;    result = false;
  696.     }
  697.  
  698.     
  699.     return result;
  700. }
  701.  
  702. /***********************************|****************************************/
  703.  
  704. Boolean T2020HalfGateway::CreateRecipientReportForLetter(T2020Letter* letter) {
  705.     Boolean    result = false;
  706.  
  707.     keithDB( "T2020Hgwy: Creating recipient report for letter" << endl << *letter );
  708.  
  709.     TRY
  710.         // Debugger () ;
  711.         
  712.         //    Sanity checking
  713.         FAILNULL(letter);
  714.  
  715.         //    Get the stuff we need to fill in the parameter block
  716.         //
  717.         BLJLetterID    letterID;
  718.         FAILifFALSE(letter->GetLetterID(letterID));
  719.  
  720.         T2020Recipient*    sender = (T2020Recipient*) letter->GetRecipient(fromRecipient, 1);
  721.         FAILNULL(sender);
  722.  
  723.         OCERecipient letterSender;
  724.         FAILifFALSE(sender->GetOCERecipient(letterSender));
  725.  
  726.         //    Create the report
  727.         //
  728.         MSAMCreateReportPB createReportPB;
  729.         CLEARBLOCK ( createReportPB );
  730.         createReportPB.queueRef = GetServerQueueID ();
  731.         createReportPB.mailMsgRef = 0;
  732.         createReportPB.msgID = * (MailLetterID*) &letterID;
  733.         createReportPB.sender = &letterSender;
  734.  
  735.         FAILOSErr(MSAMCreateReportSleep((MSAMParam*) &createReportPB));
  736.  
  737.         unsigned long recipientsInReportCount = 0;
  738.         
  739.         TRY
  740.             //    Now, cycle through all of the recipients in the letter and report each of
  741.             //    their status's we were responsible for.
  742.             for (RecipientTypeSet recipientType = toRecipient; recipientType <= bccRecipient; ++recipientType) {
  743.                 for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount(recipientType); ++recipientIndex) {
  744.                     T2020Recipient* recipient = (T2020Recipient*) letter->GetRecipient(recipientType, recipientIndex);
  745.                     
  746.                     if ((recipient) && (recipient->GetResponsible() && ( recipient->GetOriginalRecipientIndex() > 0 ) )) {
  747.                         T2020Recipient* recipient = (T2020Recipient*) letter->GetRecipient(recipientType, recipientIndex);
  748.         
  749.                         MSAMPutRecipientReportPB    putRecipientReportPB;
  750.                         CLEARBLOCK ( putRecipientReportPB );
  751.                         putRecipientReportPB.mailMsgRef = createReportPB.mailMsgRef;
  752.                         putRecipientReportPB.recipientIndex = recipient->GetOriginalRecipientIndex();
  753.                         
  754.                         keithDB ( "T2020Hgwy: CreateRecReport…, " << *recipient );
  755.  
  756.                         TRY
  757.                             if ( ConvertStatusToAOCERecpientStatusCode ( recipient->GetStatus(), putRecipientReportPB.result ) )
  758.                             {
  759.                                 FAILOSErr( MSAMPutRecipientReportSleep ( (MSAMParam*) & putRecipientReportPB ) );
  760.                                 recipientsInReportCount += 1;
  761.                             }
  762.                             
  763.                         EXCEPTION
  764.                             keithDB ( "T2020Hgwy::CreateRecipientReportForLetter, not submitting recipient report." );
  765.  
  766.                             MSAMSubmitPB abortPB;
  767.                             
  768.                             CLEARBLOCK ( abortPB );
  769.                             abortPB.mailMsgRef = createReportPB.mailMsgRef;
  770.                             abortPB.submitFlag = false;
  771.                             FAILOSErr( MSAMSubmit( (MSAMParam*) & abortPB ) );
  772.                 
  773.                             PASSEXCEPTION();
  774.                         
  775.                         ENDEXCEPTION
  776.                     }
  777.                 }
  778.             }
  779.     
  780.             if ( recipientsInReportCount <= 0 )
  781.                 keithF ( 2, "T2020HGwy::CreateRecReport, created recipient report with letter with no responsible recipients." );
  782.     
  783.             //    Now submit the report, cuz we're done
  784.             MSAMSubmitPB    submitPB;
  785.             CLEARBLOCK ( submitPB );
  786.             submitPB.mailMsgRef = createReportPB.mailMsgRef;
  787.             submitPB.submitFlag = ( recipientsInReportCount > 0 );
  788.  
  789.             FAILOSErr(MSAMSubmit((MSAMParam*) &submitPB));
  790.  
  791.         EXCEPTION
  792.             result = false;
  793.             
  794.             PASSEXCEPTION();
  795.             
  796.         ENDEXCEPTION
  797.  
  798.         result = true;
  799.  
  800.     EXCEPTION
  801.         result = false;
  802.  
  803.     ENDEXCEPTION
  804.  
  805.     return result;
  806. }
  807.  
  808. /***********************************|****************************************/
  809.  
  810. void T2020HalfGateway::PutPictureIntoLetter (long letterRef, TLetter* receivedLetter) 
  811. {
  812.     Handle picH;
  813.     
  814.     picH = GetResource ('PICT', pictID);
  815.     if ( (receivedLetter->GetSegmentCount( 'SCON' ) > 0) && picH) 
  816.     {
  817.         HLock(picH);
  818.  
  819.         MSAMPutContentPB pb;
  820.  
  821.         pb.mailMsgRef = letterRef;
  822.         pb.segmentType = kMailPictSegmentType;
  823.         pb.append = false;
  824.         pb.buffer = AllocateMailBuffer(GetHandleSize(picH), (Ptr) *picH, GetHandleSize(picH));
  825.  
  826. #if debug
  827.         keith << "2020HGwy: pb.buffer.dataSize = " << pb.buffer.dataSize << "pb.BufferPtr=" << pb.buffer.buffer << endl << flush;
  828. #endif
  829.  
  830.         pb.buffer.bufferSize = pb.buffer.dataSize;
  831.  
  832.         OSErr err = MSAMPutContentSleep((MSAMParam*) &pb);
  833.  
  834. #if debug
  835.         if (err || keithFlag.Flag(2))
  836.             keith << "T2020HGwy: MSAMPutContent, err=" << err << endl;
  837. #endif
  838.  
  839. //         DisposeMailBuffer(pb.buffer);
  840.         ReleaseResource (picH);
  841.     }
  842. }
  843.  
  844. /***********************************|****************************************/
  845.  
  846. BLJTime NowBLJTime ( )
  847. {
  848.     BLJTime result;
  849.     MachineLocation loc;
  850.     
  851.     
  852.     result.time = GetCurrentGMTSeconds ();
  853.     result.offset = 0;
  854.  
  855.     return result;    
  856. }
  857.  
  858. /***********************************|****************************************/
  859.  
  860. int operator < ( const BLJTime& i1, const BLJTime& i2 )
  861. {
  862.     return ( i1.time + i1.offset < i2.time + i2.offset );
  863. }
  864.  
  865. /***********************************|****************************************/
  866.  
  867. int operator <= ( const BLJTime& i1, const BLJTime& i2 )
  868. {
  869.     return ( i1.time + i1.offset <= i2.time + i2.offset );
  870. }
  871.  
  872. /***********************************|****************************************/
  873.  
  874. int operator == ( const BLJTime& i1, const BLJTime& i2 )
  875. {
  876.     return ( i1.time + i1.offset == i2.time + i2.offset );
  877. }
  878.  
  879. /***********************************|****************************************/
  880.  
  881. int operator > ( const BLJTime& i1, const BLJTime& i2 )
  882. {
  883.     return ( i1.time + i1.offset > i2.time + i2.offset );
  884. }
  885.  
  886. /***********************************|****************************************/
  887.  
  888. int operator >= ( const BLJTime& i1, const BLJTime& i2 )
  889. {
  890.     return ( i1.time + i1.offset >= i2.time + i2.offset );
  891. }
  892.  
  893. /***********************************|****************************************/
  894.  
  895. void T2020HalfGateway::PeriodicTasks ()
  896. {
  897.     Boolean done = false;
  898.     
  899.     do {    
  900.     
  901.         //    Every so often, check through the fLettersWaitingForRecipientReports list
  902.         //    and remove any item that has been there more than 7 days.
  903.         
  904.         if ( fLettersWaitingForRecipientReportsCountdownTimer.ExpiredYet () )
  905.         {
  906.             if ( fLettersWaitingForRecipientReportsCountdownTimer.ExpirationCount () > 1 )
  907.                 for ( unsigned long i = 1 ; i <= fLettersWaitingForRecipientReports.Count () ; ++ i )
  908.                 {
  909.                     TLetter* letter = fLettersWaitingForRecipientReports.Get ( i );
  910.                     
  911.                     if ( letter )
  912.                     {    BLJTime    sendTime;
  913.                         if ( letter->GetSendTimeStamp ( sendTime ) && ( sendTime <= NowBLJTime ( ) ) )
  914.                         {
  915.                             fLettersWaitingForRecipientReports.Remove ( letter );
  916.                             TLetter::SetAllUnknownRecipientStatus ( letter, cTimedOut );
  917.                             if ( ! letter->LetterIsCompleted () )
  918.                                 delete letter;
  919.                         }
  920.                     }
  921.                 }
  922.             
  923.             fLettersWaitingForRecipientReportsCountdownTimer.ResetTimer () ;
  924.         }
  925.         
  926.     
  927.         //    Fill in some config fields from the config database.
  928.         {    CTupleKey key ("2020DoNotSendLetters");
  929.             CDataItem buffer;
  930.         
  931.             if (GetConfigItem(key, buffer))
  932.                 fDoNotSendLetters = * (Boolean *) buffer.GetPhysicalStart();
  933.             else
  934.                 fDoNotSendLetters = false;
  935.         }
  936.         
  937.         {    CTupleKey key ("2020DoNotReceiveLetters");
  938.             CDataItem buffer;
  939.         
  940.             if (GetConfigItem(key, buffer))
  941.                 fDoNotReceiveLetters = * (Boolean *) buffer.GetPhysicalStart();
  942.             else
  943.                 fDoNotReceiveLetters = false;
  944.         }
  945.  
  946.         TSleep(60*15);
  947.         
  948.     } while ((IsHalfGatewayShuttingDown() == false) && (done == false));
  949.  
  950. }
  951.  
  952. /***********************************|****************************************/
  953.  
  954. //
  955. //    STATUS REPORTING / ERROR REPORTING OPTIONS
  956. //    ==========================================
  957. //
  958. Boolean T2020HalfGateway::GetStatusItem(const ATupleKey& key, ADataItem& data)
  959. {    Boolean result = false;
  960.  
  961.     if (key.GetLength() == sizeof(OSType)) {
  962.         OSType keyType = * (OSType *) key.GetData();
  963.         
  964.         switch (keyType) {
  965.             case 'OCPL':    //    Count-of-Pending-Letters
  966.                 data = fReceivedLetters.Count();
  967.                 result = true;
  968.                 break;
  969.  
  970.             case 'OCAL':    //    Count-of-Acknowledgement-waiting-Letters
  971.                 data = fLettersWaitingForRecipientReports.Count();
  972.                 result = true;
  973.                 break;
  974.                 
  975.             case 'OCLS':    //    Count-of-Letters-Sent-to-aoce
  976.                 data = fLettersSentToAOCE;
  977.                 result = true;
  978.                 break;
  979.                 
  980.             case 'OTCK':    //    Total-Content-sent-in-K
  981.                 data = fTotalKOfContentSentToAOCE;
  982.                 result = true;
  983.                 break;
  984.                 
  985.             case 'OTEK':    //    Total-Enclosure-sent-in-K
  986.                 data = fTotalKOfEnclosuresSentToAOCE;
  987.                 result = true;
  988.                 break;
  989.             
  990.             case 'NAME':    //    Gateway name, same as AOCE Forwarder record name
  991.                 data = (StringPtr) OCERToPString( ((const RecordID *) fOurForwarderRecord)->local.recordName);
  992.                 result = true;
  993.                 break;
  994.                 
  995.             case 'DESC':    //    Gateway description
  996.                 data = (StringPtr) OCERToPString ( fOurGatewayDescription );
  997.                 result = true;
  998.                 break;
  999.         }
  1000.     };
  1001.  
  1002.     //    If we don't have it yet, try in the status database...
  1003.     if (!result) {
  1004.         result = THalfGateway::GetStatusItem ( key, data );
  1005.     }
  1006.     
  1007.     return result;
  1008. }
  1009.  
  1010. /***********************************|****************************************/
  1011.  
  1012. Boolean T2020HalfGateway::SetStatusItem(const ATupleKey& key, const ADataItem& buffer)
  1013. {
  1014.     Boolean result = THalfGateway::SetStatusItem(key, buffer);
  1015.     return result;
  1016. }
  1017.  
  1018. /***********************************|****************************************/
  1019.  
  1020. Boolean T2020HalfGateway::GetStatusStr ( Str255& statusStr ) const
  1021. {
  1022.     PLstrcpy ( statusStr, fStatusStr );
  1023.     return fStatusStr[0];
  1024. }
  1025.  
  1026. /***********************************|****************************************/
  1027.  
  1028. void T2020HalfGateway::SetStatusStr ( Str255 statusStr )
  1029. {
  1030.     fMailGateway->SetStatusStr ( statusStr );
  1031.     if ( PLstrcmp ( fStatusStr, statusStr ) ) {
  1032.         keithDB ( "T2020HGwy::SetStatusStr(" << statusStr << ")" );
  1033.     }
  1034.     PLstrcpy ( fStatusStr, statusStr );
  1035. }
  1036.  
  1037. /***********************************|****************************************/
  1038.  
  1039. void T2020HalfGateway::ResetStatistics ( )
  1040. {
  1041.     fLettersSentToAOCE = 0;
  1042.     fLettersReceivedFromAOCE = 0;
  1043.     fTotalKOfContentSentToAOCE = 0;
  1044.     fTotalKOfEnclosuresSentToAOCE = 0;
  1045. }
  1046.  
  1047. /***********************************|****************************************/
  1048.  
  1049. Boolean T2020HalfGateway::HandleMonitoringEvent ( const ADataItem& event )
  1050. {    Boolean result = false;
  1051.  
  1052.     if ( event.GetPhysicalLength () == sizeof(OSType) )
  1053.     {
  1054.         OSType monitoringEvent = * ( OSType * ) event.GetPhysicalStart();
  1055.  
  1056.         switch ( monitoringEvent )
  1057.         {
  1058.             case 'RSET':        //    'Reset' statistics.
  1059.                 fLettersSentToAOCE = 
  1060.                 fLettersReceivedFromAOCE = 
  1061.                 fTotalKOfContentSentToAOCE =
  1062.                 fTotalKOfEnclosuresSentToAOCE = 0;
  1063.                 result = false;    //    we didn't 'completely' handle this event.
  1064.                 break;
  1065.         }
  1066.     }
  1067.     
  1068.     return result;
  1069. }
  1070.  
  1071. /***********************************|****************************************/
  1072.  
  1073. Boolean T2020HalfGateway::HandleRecipientReport (T2020Letter* report)
  1074. {
  1075.     Boolean result = false;
  1076.  
  1077.     TRY
  1078.         //    Get the gateway information block from the letter.  This block will contain the letterID
  1079.         //    of the letter this report is for, and we use this ID to determine which letter in the
  1080.         //    fLettersWaitingForRecipientReports. list we report for.
  1081.         OCECreatorType blockType;
  1082.         blockType.msgCreator = fOurGatewayMailExtensionType;
  1083.         blockType.msgType = kMailMSAMType;
  1084.         MyGWYIBlockRecord messageInfo;
  1085.         unsigned long actualReturnedDataSize;
  1086.  
  1087.         FAILifFALSE(report->GetLetterBlockData(blockType, 1, (void*) &messageInfo, sizeof(messageInfo), 0, actualReturnedDataSize));
  1088.  
  1089.         keithF(2,  "T2020Half::Got 'gwyi' block with this data:" << endl; DumpHex ( keith, & messageInfo, sizeof ( messageInfo ) ) );
  1090.  
  1091.         //    Now, find the letter in fLettersWaitingForRecipientReports. with the right letterID.
  1092.         TLetter* letter = nil;
  1093.  
  1094.         for (int index = 1; index <= fLettersWaitingForRecipientReports.Count(); ++index)
  1095.         {
  1096.             TLetter* tempLetter = fLettersWaitingForRecipientReports.Get(index);
  1097.  
  1098.             BLJLetterID letterID;
  1099.             if (tempLetter && tempLetter->GetLetterID(letterID))
  1100.             {
  1101.                 if ( letterID == messageInfo.letterID )
  1102.                 {
  1103.                     keithF(2, "T2020Hgwy: HandleRecipientReport, found letter " << letterID << " for report in fLettersWaitingForRecipientReports." );
  1104.  
  1105.                     letter = tempLetter;
  1106.                     break;
  1107.                 }
  1108.             }
  1109.         }
  1110.  
  1111.         if (letter == nil) 
  1112.         {
  1113.             keith << "T2020Hgwy: HandleRecipientReport, no letter for report " << messageInfo.letterID << endl;
  1114.             if ( keithFlag.Flag(2)) {
  1115.                 keith << "These are the letters in the list waiting for reports:" << endl;
  1116.                 for (int index = 1; index <= fLettersWaitingForRecipientReports.Count(); ++index)
  1117.                 {
  1118.                     TLetter* tempLetter = fLettersWaitingForRecipientReports.Get(index);
  1119.         
  1120.                     BLJLetterID letterID;
  1121.                     if (tempLetter && tempLetter->GetLetterID(letterID))
  1122.                     {
  1123.                         keith << index << ") " << letterID << "  ";
  1124.                     }
  1125.                 }
  1126.                 
  1127.                 keith << endl;
  1128.             }
  1129.             letter = nil;
  1130.         } 
  1131.         else 
  1132.         {
  1133.             //    Enumerate across all of the recipients in this report
  1134.             for (unsigned long index = 1; index <= report->GetRecipientReportStatusCount(); ++index) 
  1135.             {
  1136.                 unsigned short recipientIndex;
  1137.                 OSErr            recipientResult;
  1138.  
  1139.                 if (report->GetRecipientReportStatus (index, recipientIndex, recipientResult)) {
  1140.                     //    Find the recipientIndex-th recipient in the letter, and set it's
  1141.                     //    status to the appropriate value.
  1142.                     keithF(2, "HandleRecipientReport: #" << index << "  recipient#" << recipientIndex << " status=" << recipientResult );
  1143.                 }
  1144.             }
  1145.     
  1146.             //    Lastly, mark all of the responsible recipients as 'done', so that this letter will
  1147.             //    'go away' when it is finished.
  1148.             for (unsigned short recipientType = fromRecipient; recipientType <= bccRecipient; recipientType++) 
  1149.             {
  1150.                 for (unsigned short recipientIndex = 1; recipientIndex <= letter->GetRecipientCount((RecipientTypeSet) recipientType); ++recipientIndex) 
  1151.                 {    TRecipient*    recipient = letter->GetRecipient((RecipientTypeSet) recipientType, recipientIndex);
  1152.     
  1153.                     if ( recipient && recipient->GetResponsible())
  1154.                         letter->SetRecipientStatus((RecipientTypeSet) recipientType, recipientIndex, cReceived);
  1155.                 }
  1156.             }
  1157.     
  1158.             if (letter->GetUnknownRecipientCount() == 0) 
  1159.             {
  1160.                 keithF(2, "T2020Hgwy: HandleRecipientReport, all recipients of " << messageInfo.letterID << " are handled, deleting." );
  1161.                 
  1162.                 //    Now, we're done with the letter, so remove it from out list of letters
  1163.                 //    waiting for reports and then let the letter know that we're done with it.
  1164.                 fLettersWaitingForRecipientReports.Remove(letter);
  1165.                 
  1166.                 if (!letter->LetterIsCompleted()) {
  1167.                     delete letter;
  1168.                 }
  1169.             }
  1170.             else
  1171.             {
  1172.                 keithF(2, "T2020Hgwy: HandleRecipientReport, for letter " << messageInfo.letterID << ", " << letter->GetUnknownRecipientCount() << " recipients are unreported." );
  1173.             }
  1174.         }
  1175.         
  1176.         result = true;
  1177.  
  1178.     EXCEPTION
  1179.         result = false;
  1180.  
  1181.     ENDEXCEPTION
  1182.  
  1183.     delete report;
  1184.     
  1185.     return result;
  1186. }
  1187.  
  1188. /***********************************|****************************************
  1189.  *
  1190.  *
  1191.  *    AOCE High Level Event Handlers
  1192.  *    ==============================
  1193.  *
  1194.  *
  1195.  ***********************************|****************************************/
  1196.  
  1197. Boolean T2020HalfGateway::HandleAppleMailHighLevelEvent ( const EventRecord& event )
  1198. {    Boolean result = false;
  1199.  
  1200.     if ( ( event.what == kHighLevelEvent ) &&
  1201.          ( event.message == kMailAppleMailCreator ) )
  1202.     {
  1203.         switch ( * (long *) & event.where )
  1204.         {
  1205.             case kMailEPPCMsgPending:
  1206.                 AppleEventMsgPendingEvent ();
  1207.                 result = true;
  1208.                 break;
  1209.             
  1210.             case kMailEPPCAdmin:
  1211.                 AppleEventAdminEvent ( );
  1212.                 result = true;
  1213.                 break;
  1214.             
  1215.             default:
  1216.                 break;
  1217.         }
  1218.     }
  1219.  
  1220.     return result;
  1221. }
  1222.  
  1223. /***********************************|****************************************/
  1224.  
  1225. OSErr T2020HalfGateway::AppleEventMsgPendingEvent ( void )
  1226. {
  1227.     //    Wake up the thread that will check our AOCE queue
  1228.     if ( fScan2020ThreadH )
  1229.         fScan2020ThreadH->Wake();
  1230.     
  1231.     return noErr;
  1232. }
  1233.  
  1234. /***********************************|****************************************/
  1235.  
  1236. OSErr T2020HalfGateway::AppleEventAdminEvent ( void )
  1237. {
  1238.     //    Get the shared-memory-common-area for this event
  1239.     SMCA * smca;
  1240.     
  1241.     TargetID sender;
  1242.     unsigned long refCon;
  1243.     unsigned long dataLength = sizeof(smca);
  1244.     
  1245.     OSErr result = AcceptHighLevelEvent ( & sender, & refCon, (Ptr) & smca, & dataLength );
  1246.     if ( result == noErr )
  1247.     {
  1248.  
  1249.         if ( smca )
  1250.         {    void * voidParams = (void*) & smca->u;
  1251.         
  1252.             switch ( smca->userBytes )
  1253.             {
  1254.                 //    Our connectivity has changed
  1255.                 case kSMSAMNotifyFwdrSetupChange:
  1256.                     break;
  1257.                 
  1258.                 //    The name of our SMSAM has changed
  1259.                 case kSMSAMNotifyFwdrNameChange:
  1260.                     break;
  1261.                 
  1262.                 //    The password for our SMSAM has been changed
  1263.                 case kSMSAMNotifyFwdrPwdChange:
  1264.                     break;
  1265.                 
  1266.                 case kSMSAMGetDynamicFwdrParams:
  1267.                     SMSAMDynamicParams * dynamicParams = (SMSAMDynamicParams*) voidParams;
  1268.                     
  1269.                     dynamicParams->curDiskUsed = 7;
  1270.                     dynamicParams->curMemoryUsed = 8;
  1271.                     break;
  1272.             }
  1273.         }
  1274.         
  1275.         smca->result = noErr;
  1276.     }    
  1277.     
  1278.     return result;        
  1279. }
  1280.  
  1281. /***********************************|****************************************/
  1282.